package cn.iotnova.opus.utils;


import android.annotation.SuppressLint;
import android.media.AudioAttributes;
import android.media.AudioAttributes.Builder;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioTrack;

import androidx.annotation.NonNull;


import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

import cn.iotnova.opus.presenter.DecodeOpusPresenter;

public final class OpusPlayTask extends DecodeOpusPresenter implements Runnable {
    private final int bufferSize;
    private final AudioAttributes audioAttributes;
    private final AudioFormat audioFormat;
    private final int sessionId;
    private AudioTrack audioTrack;
    private OnOpusPlayListener onOpusPlayListener;
    private boolean isPlay;
    private FileOutputStream filePcmOutputStream;
    private BufferedOutputStream filePcmBufferedOutputStream;
    private String opusAudioPath;
    private boolean isPCM = false;

    public final OnOpusPlayListener getOnOpusPlayListener() {
        return onOpusPlayListener;
    }

    public final void setOnOpusPlayListener(OnOpusPlayListener opusPlayListener) {
        this.onOpusPlayListener = opusPlayListener;
    }

    public void opusDecode(@NonNull short[] formatShortArray) {
        opusDecode(formatShortArray);
        audioTrack.write(formatShortArray, 0, formatShortArray.length);
        if (filePcmBufferedOutputStream != null) {
            try {
                filePcmBufferedOutputStream.write(Uilts.getInstance().shortArrayToByteArray(formatShortArray));
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

    public final void stop() throws IOException {
        if (isPlay) {
            isPlay = false;
            cancelDecode();
            audioTrack.stop();
            audioTrack.release();
            if (filePcmBufferedOutputStream != null) {
                filePcmBufferedOutputStream.close();
                filePcmBufferedOutputStream = (BufferedOutputStream)null;
            }

            if (filePcmOutputStream != null) {
                filePcmOutputStream.close();
                filePcmOutputStream = null;
            }
        }

    }

    public void run() {
        audioTrack.play();
        isPlay = true;
        if (!this.isPCM) {
            decodeOpusFile(this.opusAudioPath, false);
        } else {
            readFile(this.opusAudioPath, false);
        }

        if (isPlay) {
            try {
                stop();
            } catch (IOException e) {
                e.printStackTrace();
            }
            if (onOpusPlayListener != null) {
                onOpusPlayListener.onCompere();
            }
        }

    }

    @SuppressLint("NewApi")
    public OpusPlayTask(@NonNull AudioManager audioManager, @NonNull String opusAudioPath, @NonNull String recorderDecodedPcmFilePath, boolean isPCM) throws IOException {
        opusAudioPath = opusAudioPath;
        isPCM = isPCM;
        bufferSize = AudioTrack.getMinBufferSize(DEFAULT_AUDIO_SAMPLE_RATE, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT);
        audioAttributes = (new Builder()).setLegacyStreamType(AudioManager.STREAM_MUSIC).build();
        audioFormat = (new AudioFormat.Builder()).setEncoding(AudioFormat.ENCODING_PCM_16BIT).setSampleRate(16000).setChannelMask(4).build();
        sessionId = audioManager.generateAudioSessionId();
        audioTrack = new AudioTrack(audioAttributes, audioFormat, bufferSize, AudioTrack.MODE_STREAM, sessionId);
        CharSequence var5 = (CharSequence)recorderDecodedPcmFilePath;

        if (var5 != null && var5.length() != 0 && !isPCM) {
            File filePcm = new File(recorderDecodedPcmFilePath);
            File fileDir = new File(filePcm.getParent());
            if (!fileDir.exists()) {
                fileDir.mkdirs();
            }

            if (filePcm.exists()) {
                filePcm.delete();
            }

            filePcm.createNewFile();
            filePcmOutputStream = new FileOutputStream(filePcm, true);
            filePcmBufferedOutputStream = new BufferedOutputStream(filePcmOutputStream);
        }

    }

    public void decodeOpusFile(@NonNull String path, boolean newThreadRun) {
        super.decodeOpusFile(path, newThreadRun);
    }

    public void readFile(@NonNull String path, boolean newThreadRun) {
        super.readFile(path, newThreadRun);
    }

    public void cancelDecode() {
        super.cancelDecode();
    }

    @NonNull
    public short[] byteArrayToShortArray(@NonNull byte[] byteArray) {
        return super.byteArrayToShortArray( byteArray);
    }

    public void opusDecodeFinish() {
        super.opusDecodeFinish();
    }

    public interface OnOpusPlayListener {
        void onCompere();
    }
}
